package com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.authenticator;

import com.alibaba.fastjson.JSON;
import com.zpz.framework.zpzoauth.common.result.ZpzOauthResultMsg;
import com.zpz.framework.zpzoauth.common.result.ZpzOauthResultStatus;
import com.zpz.framework.zpzoauth.common.utils.ZpzOauthCommonConstant;
import com.zpz.framework.zpzoauth.common.utils.ZpzOauthHttpUtil;
import com.zpz.framework.zpzoauth.config.oauth.authorization.exouath.ZpzOauthIntegrationAuthentication;
import com.zpz.framework.zpzoauth.pojo.qo.ModifyUserLoginDateQo;
import com.zpz.framework.zpzoauth.pojo.qo.RegisterQo;
import com.zpz.framework.zpzoauth.pojo.vo.UserAuthenticationVo;
import com.zpz.framework.zpzoauth.service.ZpzOauthFrameUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;

/**
 * @author zhangpanzhi
 * @time 2019-07-09
 * @description 未经本人允许请勿随便改动，尊重劳动
 * */
@Component
@Primary
public class ZpzOauthOneClickLoginAuthenticator extends AbstractPreparableIntegrationAuthenticator {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private ZpzOauthFrameUserService iFrameUserService  ;
    private final static String U_P_AUTH_TYPE = "one_click_login";
    @Value("${zpzOauth.oneClickLogin.url}")
    private String oneClickLoginUrl;
    @Value("${zpzOauth.oneClickLogin.key}")
    private String oneClickLoginKey;
    @Override
    public UserAuthenticationVo authenticate(ZpzOauthIntegrationAuthentication integrationAuthentication) {
        log.info("一键登录模式：入参："+ JSON.toJSONString(integrationAuthentication));
        String phone = null;
        String password =null;
        try {
            Map<String,String> map=new HashMap<>();
            password = integrationAuthentication.getAuthParameter("password");
            map.put("loginToken",password);
            Map<String,String> headers=new HashMap<>();
            headers.put("Authorization",String.format("Basic %s",integrationAuthentication.getAuthParameter("authorization")));
            String s = ZpzOauthHttpUtil.getInstance().doPostJsonString(oneClickLoginUrl, null, JSON.toJSONString(map), headers);
           if (StringUtils.isNotBlank(s)){
                Map<String,Object> re=(Map<String,Object>)JSON.parse(s);
                Object obj = re.get("phone");
                if (obj!=null){
                    phone = decrypt(obj.toString(), oneClickLoginKey);
                }
            }
        }catch (Exception e) {
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10015.getCode() +"]："+ZpzOauthResultStatus.OAUTH_10015.getMessage()+"：：："+e.getMessage());
        }
        if (!StringUtils.isNotBlank(phone)){
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10015.getCode() +"]："+ZpzOauthResultStatus.OAUTH_10015.getMessage());
        }
        ZpzOauthResultMsg<UserAuthenticationVo> re = iFrameUserService.findUserByPhoneNumber(phone,integrationAuthentication.getClientId());
        if (re==null||re.getCode()!=0){
            RegisterQo param=new RegisterQo();
            param.setPassword("");
            param.setPhoneNumber(phone);
            param.setUserName(phone);
            iFrameUserService.register(param,integrationAuthentication.getClientId());
        }
        log.info("密码模式登录：查询用户结果："+ JSON.toJSONString(re));
        integrationAuthentication.setAuthParameters(integrationAuthentication.getAuthParameters());
        if (re!=null&&re.getData()!=null&&re.getCode()==0){
            UserAuthenticationVo data = re.getData();
            data.setPassword(passwordEncoder.encode(password));
            data.setUserName(phone);
            if (!re.getData().getType().contains(integrationAuthentication.getClientId())){
                throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10008.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10008.getMessage()+"：：："+re.getMessage());
            }
            if (re.getData().getStatus().intValue()!= ZpzOauthCommonConstant.USER_STATUS_ENABLED){
                throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10009.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10009.getMessage()+"：：："+re.getMessage());
            }
            if (StringUtils.isNotBlank(data.getLockType())&&data.getLockType().contains(integrationAuthentication.getClientId())){
                throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10010.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10010.getMessage()+"：：："+re.getMessage());
            }
            ModifyUserLoginDateQo t=new ModifyUserLoginDateQo();
            t.setUserCode(data.getUserCode());
            t.setClientId(integrationAuthentication.getClientId());
            t.setLoginDate(new Date());
            ZpzOauthResultMsg<Boolean> flag = iFrameUserService.modifyUserLoginDate(t);
            log.info("::::::::::修改最新登录时间： "+JSON.toJSONString(flag));
            return data;
        }else{
            throw new OAuth2Exception("登录授权失败[ZPZ_DEFINED_OAUTH2_EXCEPTION]["+ ZpzOauthResultStatus.OAUTH_10005.getCode() +"]："+ ZpzOauthResultStatus.OAUTH_10005.getMessage()+"：：："+re.getMessage());
        }
    }

    @Override
    public void prepare(ZpzOauthIntegrationAuthentication integrationAuthentication) {

    }

    @Override
    public boolean support(ZpzOauthIntegrationAuthentication integrationAuthentication) {
    	//增加空判断，支持授权码模式
        return StringUtils.isEmpty(integrationAuthentication.getAuthType())
        		||U_P_AUTH_TYPE.equals(integrationAuthentication.getAuthType());
    }
    public  String decrypt(String cryptograph, String prikey) throws Exception {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(prikey));
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
        Cipher cipher=Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte [] b = Base64.getDecoder().decode(cryptograph);
        return new String(cipher.doFinal(b));
    }
}
